home *** CD-ROM | disk | FTP | other *** search
- /*
- RS232 - Map the serial port of the PSX to a PC COMx
- ================================================================
- This code is done for making an easy conversion to plugin format
- ================================================================
- */
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "fpse.h"
-
- //#define DEBUG_SERIAL
-
- #ifndef DEBUG_SERIAL
- #define SERPORT FPSEIni.ComName
- #else
- #define SERPORT DefaultSerialPort
- #endif
-
- static HANDLE h;
- static HANDLE hcom;
- static int rs232=0;
- static SIO_Type *SioRs232;
- static char *DefaultSerialPort = "COM1";
-
- DWORD CALLBACK ComThread( HANDLE h )
- {
- DWORD mask;
- DWORD read,ret;
- DWORD dwModemStatus;
- OVERLAPPED osRead = { 0 };
- char ch;
-
- // wait for received characters
- if( !SetCommMask(h,EV_CTS | EV_DSR | EV_RXCHAR) ) {
- printf("SetCommMask failed\n");
- return FPSE_ERR;
- }
-
- while (!rs232) ;
-
- do {
- // get the event mask
- if( WaitCommEvent(h, &mask, NULL) ) {
- #ifdef DEBUG_SERIAL
- printf("event happen\n");
- #endif
- read=0;
- if (mask & EV_RXCHAR) {
- do {
- ret = ReadFile(h,&ch,1,&read,&osRead);
- if (!ret && GetLastError() != ERROR_IO_PENDING) break;
- } while (!ret);
- if (!ret) {
- printf("Error in ReadFile(%s)\n",SERPORT);
- read = 0;
- }
- }
-
- if ( mask & (EV_CTS|EV_DSR) ) {
- if (!GetCommModemStatus(h, &dwModemStatus)) {
- printf("Error in GetCommModemStatus\n");
- break;
- }
- if (mask & EV_CTS) {
- SioRs232->Delta |= CTS;
- if (MS_CTS_ON & dwModemStatus) SioRs232->Status |= CTS;
- else SioRs232->Status &= ~CTS;
- }
- if (mask & EV_DSR) {
- SioRs232->Delta |= DSR;
- if (MS_DSR_ON & dwModemStatus) SioRs232->Status |= DSR;
- else SioRs232->Status &= ~DSR;
- }
- #ifdef DEBUG_SERIAL
- if (SioRs232->Status & CTS) printf("CTS ON\n");
- else printf("CTS OFF\n");
- if (SioRs232->Status & DSR) printf("DSR ON\n");
- else printf("DSR OFF\n");
- #endif
- }
- #ifndef DEBUG_SERIAL
- sio_async(SioRs232,&ch,read);
- #endif
- mask = 0;
- }
- } while(rs232);
-
- // tell terminal thread to quit
- printf("Shutdown serial emulator.\n");
- SetCommMask(h,0);
-
- return FPSE_OK;
- }
-
- int RS232_Init(SIO_Type *sio)
- {
- DWORD id;
- COMMTIMEOUTS timeouts;
-
- // check if the driver is already installed
- if (rs232) return FPSE_WARN;
-
- #ifndef DEBUG_SERIAL
- if (SERPORT == NULL) SERPORT = DefaultSerialPort;
- #endif
-
- // open port for overlapped I/O
- h = CreateFile(SERPORT,
- GENERIC_READ|GENERIC_WRITE,
- 0,NULL,
- OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED,
- NULL);
-
- if (h == INVALID_HANDLE_VALUE) return FPSE_ERR;
-
- // set time-out
- timeouts.ReadIntervalTimeout = 0;
- timeouts.ReadTotalTimeoutMultiplier = 0;
- timeouts.ReadTotalTimeoutConstant = 0;
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
-
- if (!SetCommTimeouts(h, &timeouts)) {
- printf("Error setting time-outs.\n");
- CloseHandle(h);
- return FPSE_ERR;
- }
-
- // Set default rate at 9600, 8bit, 1stop
- sio->Baud = SIOBAUDCLOCK/9600;
- sio->Mode = PRESCALER1 | BYTE8BIT | STOP1BIT;
- sio->IrqSrc = SIO_IRQ_IMM;
-
- // Update physical port
- RS232_UpdateStatus(sio);
-
- // Create Thread
- SioRs232 = sio;
- hcom = CreateThread(NULL,0,ComThread,h,0,&id);
- if( hcom == INVALID_HANDLE_VALUE ) {
- printf("CreateThread failed\n");
- return FPSE_ERR;
- }
-
- // Now the driver is correctly installed
- rs232 = 1;
-
- return FPSE_OK;
- }
-
- void RS232_Close(SIO_Type *sio)
- {
- if (!rs232) return;
-
- TerminateThread(hcom,0);
- CloseHandle(hcom);
- CloseHandle(h);
- rs232 = 0;
- }
-
- static BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
- {
- OVERLAPPED osWrite = {0};
- DWORD dwWritten;
- DWORD dwRes;
- BOOL fRes;
-
- // Create this write operation's OVERLAPPED structure's hEvent.
- osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (osWrite.hEvent == NULL)
- // error creating overlapped event handle
- return FALSE;
-
- // Issue write.
- if (!WriteFile(h, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- // WriteFile failed, but isn't delayed. Report error and abort.
- fRes = FALSE;
- }
- else {
- // Write is pending.
- dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
- switch(dwRes)
- {
- // OVERLAPPED structure's event has been signaled.
- case WAIT_OBJECT_0:
- if (!GetOverlappedResult(h, &osWrite, &dwWritten, TRUE)) // FALSE))
- fRes = FALSE;
- else
- // Write operation completed successfully.
- fRes = TRUE;
- break;
-
- default:
- // An error has occurred in WaitForSingleObject.
- // This usually indicates a problem with the
- // OVERLAPPED structure's event handle.
- fRes = FALSE;
- break;
- }
- }
- }
- else
- // WriteFile completed immediately.
- fRes = TRUE;
-
- CloseHandle(osWrite.hEvent);
- return fRes;
- }
-
- void RS232_WriteData(SIO_Type *sio)
- {
- if ( WriteABuffer(sio->TxBuf,sio->TxNum) != TRUE) {
- printf("WriteFile failed\n");
- }
- }
-
- void RS232_UpdateStatus(SIO_Type *sio)
- {
- DCB dcb;
-
- // set DCB
- memset(&dcb,0,sizeof(dcb));
- dcb.DCBlength = sizeof(dcb);
-
- // Setup baud rate
- switch (sio->Mode & 3) {
- case 0:
- case 1:
- dcb.BaudRate = SIOBAUDCLOCK / sio->Baud;
- break;
- case 2:
- dcb.BaudRate = SIOBAUDCLOCK / (sio->Baud*16);
- break;
- case 3:
- dcb.BaudRate = SIOBAUDCLOCK / (sio->Baud*64);
- break;
- }
-
- // Setup parity
- if (sio->Mode & PARITY) {
- if (sio->Mode & PARITY_ODDEVEN) dcb.Parity = ODDPARITY;
- else dcb.Parity = EVENPARITY;
- } else dcb.Parity = NOPARITY;
-
- // Setup byte lenght
- dcb.ByteSize = 5 + ((sio->Mode >> 2) & 0x3);
-
- // Setup stop bit lenght
- switch (sio->Mode & 0xC0) {
- case 0:
- case STOP1BIT:
- dcb.StopBits = ONESTOPBIT;
- break;
- case STOP15BIT:
- dcb.StopBits = ONE5STOPBITS;
- break;
- case STOP2BIT:
- dcb.StopBits = TWOSTOPBITS;
- break;
- }
-
- dcb.fBinary = 1;
- if (sio->Ctrl.Control8.Line & DTR) dcb.fDtrControl = DTR_CONTROL_ENABLE;
- else dcb.fDtrControl = DTR_CONTROL_DISABLE;
-
- if (sio->Ctrl.Control8.Line & RTS) dcb.fRtsControl = RTS_CONTROL_ENABLE;
- else dcb.fRtsControl = RTS_CONTROL_DISABLE;
-
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
-
- if(!SetCommState(h,&dcb))
- printf("RS232_UpdateStatus() failed\n");
- }
-
- #ifdef DEBUG_SERIAL
- #include <conio.h>
- char str[]={"ciao"};
- void main()
- {
- SIO_Type sio;
-
- sio.FifoSize = 4;
- if (RS232_Init(&sio) != FPSE_OK) {
- printf("non configuro il sio\n");
- return;
- }
-
- memcpy(sio.TxBuf,str,4);
- sio.TxNum = 4;
- RS232_WriteData(&sio);
- while (getch() != 27);
-
- RS232_Close(&sio);
- }
- #endif